使用具有 HTML 个自定义元素的模板
Use of Template with HTML Custom Elements
我刚开始学习 HTML 自定义元素,通过阅读一系列介绍、教程和文档,我认为我对它的工作原理有了很好的了解,但我有一个哲学问题关于正确使用或不使用 <template>
标签的方法。
自定义元素使您能够封装新功能,简化 HTML 文档的结构,并允许您简单地插入 <my-custom-element>...</my-custom-element>
标记而不是 <div class="my-custom-element"><span class="part1">...</span><span class="part2">...</span></div>
。
元素的 class 定义然后设置该元素的结构和功能。一堆教程然后描述了如何使用 <template>...</template>
和 <slot>...</slot>
来设置自定义元素的内容。然后,您必须将模板代码包含在每个要在其中使用该元素的 HTML 文档中,而不是在自定义元素 class 的构造函数中进行设置。这是否 运行 与自定义元素有助于简化和封装功能以使其更便携的事实相悖?还是我误解了模板在文档中的正确用法 and/or 位置?
通过 SO,我能找到的最接近解决这个问题的是这个问题:
如何使用 vanilla js 去除自包含自定义元素中的模板?
但答案基本上回避了这一切并说 "Don't use <template>
," 所以并没有真正消除我的困惑。
实际上 <template>
元素可以通过 HTML Imports 从另一个文档导入,连同将定义自定义元素的 Javascript 代码:
<link rel="import" src="my-custom-element.html">
...
<custom-element></custom-element>
因此它不需要包含在每个 HTML 文档中。
HTML 导入仅在 Chrome 和 Opera 中实现。如果你想在 Firefox 和 Safari 中使用它们,你需要使用 HTML Imports polyfill.
另一方面,Mozilla 和 Apple 暂时不打算在各自的浏览器中实现 HTML 导入。因此,他们建议使用纯 Javascript 模块(使用 import
或 <script src="...">
)定义自定义元素,并改为提升 template literals 字符串,这提供了一些优势(变量、函数),但有时在 IDE 中编码更复杂(因为它们的字符串表示形式)。
也许将来standard HTML modules会被所有浏览器采用,<template>
会重新成为人们关注的焦点...
请注意,如果没有 HTML 导入,您仍然可以使用 fetch()
:
导入一些 HTML 文档
fetch( "template.html" )
.then( stream => stream.text() )
.then( text =>
customElements.define( "c-e", class extends HTMLElement {
constructor() {
super()
this.attachShadow( { mode: 'open'} )
.innerHTML = text
}
} )
)
2019 年更新
HTML 进口 won't be supported natively after Chrome 73。然后,您应该使用上面列出的其他解决方案(polyfill、备用模块加载器、JS import
,或使用 fetch
直接下载)。
免责声明:我是下面提到的 rich-component 库的作者。
经过一段时间对自定义元素的试验并最近提出了一个完全基于它们的完整项目后,我想分享我对此的见解:
- 任何微小的组件都有可能成长为某种野兽
- HTML 一部分可能会长到非常不方便放在JS中的地步
- do 使用模板,构建和解析一次,然后克隆并注入影子根 - 这与使用文档片段而不是改变 a 的最佳实践相同生活 DOM
- 如果模板内容应该从组件的实例更改为实例 - 可以使用某种数据绑定框架,并且如果采用极简主义方法 - 处理克隆可能仍然更容易和更高效-来自模板文档片段而不是对字符串或模板文字进行操作
为了不一遍又一遍地写同样的几十行,我准备了rich-component库,其中:
- 标准化一些 API 用于模板配置和所有那些“克隆模板、创建影子、将模板的内容注入其中”的重复代码行
- 已知在提供 html URL 时获取 html 内容
- 缓存模板,因此提取仅完成一次
我刚开始学习 HTML 自定义元素,通过阅读一系列介绍、教程和文档,我认为我对它的工作原理有了很好的了解,但我有一个哲学问题关于正确使用或不使用 <template>
标签的方法。
自定义元素使您能够封装新功能,简化 HTML 文档的结构,并允许您简单地插入 <my-custom-element>...</my-custom-element>
标记而不是 <div class="my-custom-element"><span class="part1">...</span><span class="part2">...</span></div>
。
元素的 class 定义然后设置该元素的结构和功能。一堆教程然后描述了如何使用 <template>...</template>
和 <slot>...</slot>
来设置自定义元素的内容。然后,您必须将模板代码包含在每个要在其中使用该元素的 HTML 文档中,而不是在自定义元素 class 的构造函数中进行设置。这是否 运行 与自定义元素有助于简化和封装功能以使其更便携的事实相悖?还是我误解了模板在文档中的正确用法 and/or 位置?
通过 SO,我能找到的最接近解决这个问题的是这个问题:
如何使用 vanilla js 去除自包含自定义元素中的模板?
但答案基本上回避了这一切并说 "Don't use <template>
," 所以并没有真正消除我的困惑。
实际上 <template>
元素可以通过 HTML Imports 从另一个文档导入,连同将定义自定义元素的 Javascript 代码:
<link rel="import" src="my-custom-element.html">
...
<custom-element></custom-element>
因此它不需要包含在每个 HTML 文档中。
HTML 导入仅在 Chrome 和 Opera 中实现。如果你想在 Firefox 和 Safari 中使用它们,你需要使用 HTML Imports polyfill.
另一方面,Mozilla 和 Apple 暂时不打算在各自的浏览器中实现 HTML 导入。因此,他们建议使用纯 Javascript 模块(使用 import
或 <script src="...">
)定义自定义元素,并改为提升 template literals 字符串,这提供了一些优势(变量、函数),但有时在 IDE 中编码更复杂(因为它们的字符串表示形式)。
也许将来standard HTML modules会被所有浏览器采用,<template>
会重新成为人们关注的焦点...
请注意,如果没有 HTML 导入,您仍然可以使用 fetch()
:
fetch( "template.html" )
.then( stream => stream.text() )
.then( text =>
customElements.define( "c-e", class extends HTMLElement {
constructor() {
super()
this.attachShadow( { mode: 'open'} )
.innerHTML = text
}
} )
)
2019 年更新
HTML 进口 won't be supported natively after Chrome 73。然后,您应该使用上面列出的其他解决方案(polyfill、备用模块加载器、JS import
,或使用 fetch
直接下载)。
免责声明:我是下面提到的 rich-component 库的作者。
经过一段时间对自定义元素的试验并最近提出了一个完全基于它们的完整项目后,我想分享我对此的见解:
- 任何微小的组件都有可能成长为某种野兽
- HTML 一部分可能会长到非常不方便放在JS中的地步
- do 使用模板,构建和解析一次,然后克隆并注入影子根 - 这与使用文档片段而不是改变 a 的最佳实践相同生活 DOM
- 如果模板内容应该从组件的实例更改为实例 - 可以使用某种数据绑定框架,并且如果采用极简主义方法 - 处理克隆可能仍然更容易和更高效-来自模板文档片段而不是对字符串或模板文字进行操作
为了不一遍又一遍地写同样的几十行,我准备了rich-component库,其中:
- 标准化一些 API 用于模板配置和所有那些“克隆模板、创建影子、将模板的内容注入其中”的重复代码行
- 已知在提供 html URL 时获取 html 内容
- 缓存模板,因此提取仅完成一次